package net.slteam.base.support;

import net.slteam.base.ISLEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * ClassName: ISLEnumMybatisHandler
 * Description: ISLEnum 对Mybatis-Plus或Tk.Mybatis支持
 * date: 2019-10-10 17:42
 *
 * @author calm
 * @since JDK 1.8
 */

@SuppressWarnings("unused")
public class SLEnumMybatisHandler<E extends ISLEnum> extends BaseTypeHandler<E> {

    private Class<E> type;

    private E[] enums;

    public SLEnumMybatisHandler() {
    }

    public SLEnumMybatisHandler(Class<E> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
//        this.enums = this.type.getEnumConstants();
//        if (this.enums == null) {
//            throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
//        }
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            ps.setObject(i, parameter.getCode());
        } else
        {
            ps.setObject(i, parameter.getCode(), jdbcType.TYPE_CODE);
        }
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {

        Object code = rs.getObject(columnName);

        if (rs.wasNull()) {
            return null;
        }

        return getEnmByCode(code);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Object code = rs.getObject(columnIndex);
        if (rs.wasNull()) {
            return null;
        }

        return getEnmByCode(code);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Object code = cs.getObject(columnIndex);
        if (cs.wasNull()) {
            return null;
        }

        return getEnmByCode(code);
    }

    private E getEnmByCode(Object code) {


        if (code == null) {
            throw new NullPointerException("the result code is null " + code);
        }

        if (code instanceof Integer) {

            this.enums = this.type.getEnumConstants();
            if (this.enums == null) {
                throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
            }

            for (E e : enums) {
                if (e.getCode() == code) {
                    return e;
                }
            }
            throw new IllegalArgumentException("Unknown enumeration type , please check the enumeration code :  " + code);
        }


        if (code instanceof String) {
            for (E e : enums) {
                if (code.equals(e.getCode())) {
                    return e;
                }
            }
            throw new IllegalArgumentException("Unknown enumeration type , please check the enumeration code :  " + code);
        }

        throw new IllegalArgumentException("Unknown enumeration type , please check the enumeration code :  " + code);
    }


}
